<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Web版轴承监控系统 - {{ test_name }}</title>
    
    <!-- 引入Chart.js用于图表显示 -->
    <script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
    <script src="https://cdn.socket.io/4.5.0/socket.io.min.js"></script>
    
    <style>
        * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
        }
        
        body {
            font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
            background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
            min-height: 100vh;
            padding: 20px;
        }
        
        .container {
            max-width: 1400px;
            margin: 0 auto;
            background: rgba(255, 255, 255, 0.95);
            border-radius: 15px;
            box-shadow: 0 20px 40px rgba(0,0,0,0.1);
            overflow: hidden;
        }
        
        .header {
            background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
            color: white;
            padding: 30px;
            text-align: center;
        }
        
        .header h1 {
            font-size: 2.5em;
            margin-bottom: 10px;
            text-shadow: 0 2px 4px rgba(0,0,0,0.3);
        }
        
        .header .info {
            display: flex;
            justify-content: space-around;
            margin-top: 20px;
            flex-wrap: wrap;
        }
        
        .info-item {
            background: rgba(255,255,255,0.2);
            padding: 10px 20px;
            border-radius: 25px;
            margin: 5px;
            font-weight: 500;
        }
        
        /* 启动检测结果样式 */
        .startup-tests {
            background: rgba(255,255,255,0.1);
            margin: 20px;
            padding: 20px;
            border-radius: 10px;
            border: 2px solid rgba(255,255,255,0.2);
        }
        
        .startup-tests h3 {
            margin-bottom: 15px;
            font-size: 1.2em;
        }
        
        .test-results {
            display: grid;
            grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
            gap: 10px;
        }
        
        .test-item {
            display: flex;
            align-items: center;
            padding: 8px 12px;
            background: rgba(255,255,255,0.1);
            border-radius: 8px;
            font-size: 0.9em;
        }
        
        .test-icon {
            margin-right: 8px;
            font-size: 1.2em;
        }
        
        .test-status-all_passed {
            border-left: 4px solid #51cf66;
        }
        
        .test-status-partial_passed {
            border-left: 4px solid #ff922b;
        }
        
        .test-status-all_failed {
            border-left: 4px solid #ff6b6b;
        }
        
        .test-status-not_tested {
            border-left: 4px solid #868e96;
        }
        
        .dashboard {
            display: grid;
            grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
            gap: 20px;
            padding: 20px;
        }
        
        .card {
            background: white;
            border-radius: 10px;
            padding: 20px;
            box-shadow: 0 5px 15px rgba(0,0,0,0.08);
            transition: transform 0.3s ease, box-shadow 0.3s ease;
        }
        
        .card:hover {
            transform: translateY(-5px);
            box-shadow: 0 10px 25px rgba(0,0,0,0.15);
        }
        
        .card h3 {
            color: #333;
            margin-bottom: 15px;
            font-size: 1.3em;
            border-bottom: 2px solid #667eea;
            padding-bottom: 8px;
        }
        
        .status-grid {
            display: grid;
            grid-template-columns: repeat(2, 1fr);
            gap: 15px;
        }
        
        .status-item {
            background: #f8f9ff;
            padding: 15px;
            border-radius: 8px;
            border-left: 4px solid #667eea;
        }
        
        .status-value {
            font-size: 1.8em;
            font-weight: bold;
            color: #333;
            margin-top: 5px;
        }
        
        .status-label {
            color: #666;
            font-size: 0.9em;
        }
        
        .chart-container {
            position: relative;
            height: 300px;
            margin: 15px 0;
        }
        
        .controls {
            display: flex;
            gap: 10px;
            flex-wrap: wrap;
            margin: 15px 0;
        }
        
        .btn {
            background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
            color: white;
            border: none;
            padding: 12px 24px;
            border-radius: 25px;
            cursor: pointer;
            font-weight: 500;
            transition: all 0.3s ease;
            text-decoration: none;
            display: inline-block;
        }

        .btn:hover:not(:disabled) {
            transform: translateY(-2px);
            box-shadow: 0 5px 15px rgba(102, 126, 234, 0.4);
        }

        .btn:active:not(:disabled) {
            transform: translateY(0);
        }

        .btn:disabled {
            opacity: 0.5;
            cursor: not-allowed;
        }

        .btn-start {
            background: linear-gradient(135deg, #51cf66 0%, #37b24d 100%);
        }

        .btn-start:hover:not(:disabled) {
            box-shadow: 0 5px 15px rgba(81, 207, 102, 0.4);
        }

        .btn-stop {
            background: linear-gradient(135deg, #ff6b6b 0%, #fa5252 100%);
        }

        .btn-stop:hover:not(:disabled) {
            box-shadow: 0 5px 15px rgba(255, 107, 107, 0.4);
        }

        .btn-report {
            background: linear-gradient(135deg, #4dabf7 0%, #228be6 100%);
        }

        .btn-report:hover:not(:disabled) {
            box-shadow: 0 5px 15px rgba(77, 171, 247, 0.4);
        }
        
        .connection-status {
            position: fixed;
            top: 20px;
            right: 20px;
            padding: 10px 20px;
            border-radius: 25px;
            color: white;
            font-weight: 500;
            z-index: 1000;
            transition: all 0.3s ease;
        }
        
        .connected {
            background: #51cf66;
        }
        
        .disconnected {
            background: #ff6b6b;
        }
        
        .photos-grid {
            display: grid;
            grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
            gap: 15px;
            max-height: 400px;
            overflow-y: auto;
        }
        
        .photo-item {
            position: relative;
            border-radius: 8px;
            overflow: hidden;
            box-shadow: 0 3px 10px rgba(0,0,0,0.1);
            transition: transform 0.3s ease;
        }
        
        .photo-item:hover {
            transform: scale(1.05);
        }
        
        .photo-item img {
            width: 100%;
            height: 120px;
            object-fit: cover;
        }
        
        .photo-timestamp {
            position: absolute;
            bottom: 0;
            left: 0;
            right: 0;
            background: linear-gradient(transparent, rgba(0,0,0,0.8));
            color: white;
            padding: 5px;
            font-size: 0.8em;
            text-align: center;
        }
        
        .anomaly-list {
            max-height: 300px;
            overflow-y: auto;
        }
        
        .anomaly-item {
            background: #fff5f5;
            border-left: 4px solid #ff6b6b;
            padding: 10px;
            margin: 5px 0;
            border-radius: 5px;
        }
        
        .anomaly-item.medium {
            background: #fff8f0;
            border-color: #ff922b;
        }
        
        .anomaly-item.low {
            background: #f0fff4;
            border-color: #51cf66;
        }
        
        .loading {
            text-align: center;
            padding: 20px;
            color: #666;
        }
        
        .spinner {
            border: 4px solid #f3f3f3;
            border-top: 4px solid #667eea;
            border-radius: 50%;
            width: 40px;
            height: 40px;
            animation: spin 1s linear infinite;
            margin: 0 auto 20px;
        }
        
        @keyframes spin {
            0% { transform: rotate(0deg); }
            100% { transform: rotate(360deg); }
        }
        
        .alert {
            position: fixed;
            top: 80px;
            right: 20px;
            max-width: 300px;
            padding: 15px;
            border-radius: 8px;
            color: white;
            font-weight: 500;
            z-index: 1001;
            transform: translateX(100%);
            transition: transform 0.3s ease;
        }
        
        .alert.show {
            transform: translateX(0);
        }
        
        .alert-success {
            background: #51cf66;
        }
        
        .alert-error {
            background: #ff6b6b;
        }
        
        .alert-warning {
            background: #ff922b;
        }
        
        /* 模块测试详情样式 */
        .module-tests-card {
            grid-column: 1 / -1;
        }
        
        .module-test-grid {
            display: grid;
            grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
            gap: 15px;
            margin-top: 15px;
        }
        
        .module-test-item {
            border: 1px solid #e9ecef;
            border-radius: 8px;
            padding: 15px;
            background: #f8f9fa;
        }
        
        .module-test-item.passed {
            border-color: #51cf66;
            background: #f0fff4;
        }
        
        .module-test-item.failed {
            border-color: #ff6b6b;
            background: #fff5f5;
        }
        
        .module-test-header {
            display: flex;
            align-items: center;
            margin-bottom: 10px;
        }
        
        .module-test-icon {
            margin-right: 10px;
            font-size: 1.5em;
        }
        
        .module-test-name {
            font-weight: bold;
            font-size: 1.1em;
        }
        
        .module-test-status {
            margin-left: auto;
            padding: 4px 8px;
            border-radius: 4px;
            font-size: 0.8em;
            font-weight: bold;
        }
        
        .status-passed {
            background: #51cf66;
            color: white;
        }
        
        .status-failed {
            background: #ff6b6b;
            color: white;
        }
        
        .status-testing {
            background: #ff922b;
            color: white;
        }
        
        .module-test-message {
            color: #666;
            font-size: 0.9em;
            margin-bottom: 8px;
        }
        
        .module-test-duration {
            color: #868e96;
            font-size: 0.8em;
        }

        /* 配置按钮样式 */
        .btn-config {
            position: fixed;
            bottom: 20px;
            right: 20px;
            width: 60px;
            height: 60px;
            border-radius: 50%;
            background: linear-gradient(135deg, #ff922b 0%, #fd7e14 100%);
            color: white;
            border: none;
            font-size: 24px;
            cursor: pointer;
            box-shadow: 0 5px 20px rgba(255, 146, 43, 0.4);
            transition: all 0.3s ease;
            z-index: 999;
            display: flex;
            align-items: center;
            justify-content: center;
        }

        .btn-config:hover {
            transform: scale(1.1) rotate(90deg);
            box-shadow: 0 8px 30px rgba(255, 146, 43, 0.6);
        }

        /* 模态框样式 */
        .modal {
            display: none;
            position: fixed;
            z-index: 2000;
            left: 0;
            top: 0;
            width: 100%;
            height: 100%;
            background-color: rgba(0,0,0,0.6);
            animation: fadeIn 0.3s;
        }

        .modal.show {
            display: flex;
            align-items: center;
            justify-content: center;
        }

        @keyframes fadeIn {
            from { opacity: 0; }
            to { opacity: 1; }
        }

        .modal-content {
            background-color: white;
            padding: 30px;
            border-radius: 15px;
            width: 90%;
            max-width: 600px;
            max-height: 90vh;
            overflow-y: auto;
            box-shadow: 0 20px 60px rgba(0,0,0,0.3);
            animation: slideIn 0.3s;
        }

        @keyframes slideIn {
            from {
                transform: translateY(-50px);
                opacity: 0;
            }
            to {
                transform: translateY(0);
                opacity: 1;
            }
        }

        .modal-header {
            display: flex;
            justify-content: space-between;
            align-items: center;
            margin-bottom: 25px;
            padding-bottom: 15px;
            border-bottom: 2px solid #667eea;
        }

        .modal-header h2 {
            color: #667eea;
            margin: 0;
            font-size: 1.8em;
        }

        .modal-close {
            background: none;
            border: none;
            font-size: 28px;
            cursor: pointer;
            color: #999;
            transition: color 0.3s;
            line-height: 1;
        }

        .modal-close:hover {
            color: #ff6b6b;
        }

        .form-group {
            margin-bottom: 20px;
        }

        .form-group label {
            display: block;
            margin-bottom: 8px;
            color: #333;
            font-weight: 500;
            font-size: 1em;
        }

        .form-group input,
        .form-group select {
            width: 100%;
            padding: 12px 15px;
            border: 2px solid #e0e0e0;
            border-radius: 8px;
            font-size: 1em;
            transition: border-color 0.3s;
            box-sizing: border-box;
        }

        .form-group input:focus,
        .form-group select:focus {
            outline: none;
            border-color: #667eea;
        }

        .form-group small {
            display: block;
            margin-top: 5px;
            color: #666;
            font-size: 0.85em;
        }

        .form-row {
            display: grid;
            grid-template-columns: 1fr 1fr;
            gap: 15px;
        }

        .modal-footer {
            display: flex;
            justify-content: flex-end;
            gap: 10px;
            margin-top: 30px;
            padding-top: 20px;
            border-top: 1px solid #e0e0e0;
        }

        .btn-cancel {
            background: #868e96;
        }

        .btn-cancel:hover {
            background: #6c757d;
            box-shadow: 0 5px 15px rgba(108, 117, 125, 0.4);
        }

        .btn-save {
            background: linear-gradient(135deg, #51cf66 0%, #37b24d 100%);
        }

        .btn-save:hover {
            box-shadow: 0 5px 15px rgba(81, 207, 102, 0.4);
        }

        @media (max-width: 768px) {
            .dashboard {
                grid-template-columns: 1fr;
            }

            .header .info {
                flex-direction: column;
                align-items: center;
            }

            .controls {
                justify-content: center;
            }

            .test-results {
                grid-template-columns: 1fr;
            }

            .module-test-grid {
                grid-template-columns: 1fr;
            }

            .form-row {
                grid-template-columns: 1fr;
            }

            .modal-content {
                width: 95%;
                padding: 20px;
            }
        }
    </style>
</head>
<body>
    <div id="connection-status" class="connection-status disconnected">
        🔴 连接中...
    </div>
    
    <div id="alert-container"></div>

    <!-- 配置按钮 -->
    <button class="btn-config" onclick="openConfigModal()" title="配置">⚙️</button>

    <!-- 配置模态框 -->
    <div id="configModal" class="modal">
        <div class="modal-content">
            <div class="modal-header">
                <h2>⚙️ 系统配置</h2>
                <button class="modal-close" onclick="closeConfigModal()">&times;</button>
            </div>
            <form id="configForm">
                <div class="form-group">
                    <label for="device_type">🏭 设备类型</label>
                    <select id="device_type" name="device_type">
                        <option value="轴承">轴承</option>
                        <option value="水泵">水泵</option>
                        <option value="电机">电机</option>
                        <option value="风机">风机</option>
                        <option value="齿轮箱">齿轮箱</option>
                        <option value="压缩机">压缩机</option>
                        <option value="其他">其他</option>
                    </select>
                    <small>选择被监控的设备类型</small>
                </div>

                <div class="form-group">
                    <label for="test_name">📋 测试名称</label>
                    <input type="text" id="test_name" name="test_name" placeholder="例如: production_test_001">
                    <small>用于标识本次测试，将作为数据文件夹名称</small>
                </div>

                <div class="form-group">
                    <label for="operator">👤 操作员</label>
                    <input type="text" id="operator" name="operator" placeholder="例如: 张三">
                    <small>执行本次测试的操作员姓名</small>
                </div>

                <div class="form-group">
                    <label for="bearing_model">⚙️ 设备型号</label>
                    <input type="text" id="bearing_model" name="bearing_model" placeholder="例如: 6204-2RS">
                    <small>被测试的设备型号</small>
                </div>

                <div class="form-group">
                    <label for="client">🏢 委托人</label>
                    <input type="text" id="client" name="client" placeholder="例如: XX公司">
                    <small>委托检测的单位或个人</small>
                </div>

                <div class="form-group">
                    <label for="test_nature">📝 检测性质</label>
                    <select id="test_nature" name="test_nature">
                        <option value="">请选择...</option>
                        <option value="委托检测">委托检测</option>
                        <option value="定期检测">定期检测</option>
                        <option value="抽样检测">抽样检测</option>
                        <option value="新品检测">新品检测</option>
                        <option value="故障分析">故障分析</option>
                        <option value="其他">其他</option>
                    </select>
                    <small>本次检测的性质类型</small>
                </div>

                <div class="modal-footer">
                    <button type="button" class="btn btn-cancel" onclick="closeConfigModal()">取消</button>
                    <button type="submit" class="btn btn-save">💾 保存配置</button>
                </div>
            </form>

            <!-- 数据下载部分 -->
            <div style="margin-top: 30px; padding-top: 30px; border-top: 2px solid #e0e0e0;">
                <h3 style="color: #667eea; margin-bottom: 15px; font-size: 1.4em;">📥 数据下载</h3>
                <p style="color: #666; margin-bottom: 15px; font-size: 0.9em;">下载监控会话数据（所有数据已保存在 monitoring_sessions 目录）</p>

                <!-- 最新会话下载 -->
                <h4 style="color: #764ba2; margin-bottom: 10px; font-size: 1.1em;">📦 快速下载</h4>
                <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); gap: 15px; margin-bottom: 25px;">
                    <button onclick="downloadLatestSession()" class="btn" style="text-align: center; padding: 15px; cursor: pointer;">
                        📥 下载最新会话数据包<br>
                        <small style="opacity: 0.8; font-size: 0.8em;">包含所有监控数据（CSV、照片、录音、报告）</small>
                    </button>
                </div>

                <!-- 历史会话查询下载 -->
                <h4 style="color: #764ba2; margin-bottom: 10px; font-size: 1.1em;">📂 历史数据查询</h4>
                <div style="margin-bottom: 15px;">
                    <button onclick="showSessionsModal()" class="btn" style="padding: 12px 24px;">
                        🔍 查看所有历史会话
                    </button>
                </div>

                <!-- 当前会话分类下载 -->
                <h4 style="color: #764ba2; margin-bottom: 10px; font-size: 1.1em;">📝 当前会话分类下载</h4>
                <p style="color: #999; margin-bottom: 10px; font-size: 0.85em;">⚠️ 仅下载当前会话的特定类型数据</p>
                <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 15px;">
                    <a href="/api/download/monitoring_csv" class="btn" style="text-align: center; padding: 15px;">
                        📊 完整监控数据<br>
                        <small style="opacity: 0.8; font-size: 0.8em;">CSV格式</small>
                    </a>
                    <a href="/api/download/temperature_csv" class="btn" style="text-align: center; padding: 15px;">
                        🌡️ 温度数据<br>
                        <small style="opacity: 0.8; font-size: 0.8em;">CSV格式</small>
                    </a>
                    <a href="/api/download/vibration_csv" class="btn" style="text-align: center; padding: 15px;">
                        📈 振动数据<br>
                        <small style="opacity: 0.8; font-size: 0.8em;">CSV格式</small>
                    </a>
                    <a href="/api/download/audio_recordings" class="btn" style="text-align: center; padding: 15px;">
                        🔊 音频录音<br>
                        <small style="opacity: 0.8; font-size: 0.8em;">ZIP压缩包</small>
                    </a>
                </div>

                <!-- 报告查看部分 -->
                <div style="margin-top: 30px; padding-top: 30px; border-top: 2px solid #e0e0e0;">
                    <h3 style="color: #667eea; margin-bottom: 15px; font-size: 1.4em;">📄 报告查看</h3>
                    <p style="color: #666; margin-bottom: 15px; font-size: 0.9em;">查看和下载已生成的检测报告</p>

                    <div style="margin-bottom: 15px;">
                        <button onclick="showReportsModal()" class="btn" style="padding: 12px 24px;">
                            📋 查看所有报告
                        </button>
                    </div>
                </div>
            </div>
        </div>
    </div>

    <!-- 报告列表模态框 -->
    <div id="reportsModal" class="modal">
        <div class="modal-content" style="max-width: 900px;">
            <div class="modal-header">
                <h2>📄 检测报告列表</h2>
                <button class="modal-close" onclick="closeReportsModal()">&times;</button>
            </div>
            <div id="reports-list-container" style="max-height: 500px; overflow-y: auto;">
                <div class="loading">
                    <div class="spinner"></div>
                    <div>加载报告列表中...</div>
                </div>
            </div>
        </div>
    </div>

    <div class="container">
        <div class="header">
            <h1>🔧 Web版{{ device_type }}监控系统</h1>
            <div class="info">
                <div class="info-item">📋 测试: {{ test_name }}</div>
                <div class="info-item">👤 操作员: {{ operator }}</div>
                <div class="info-item">⚙️ 设备型号: {{ bearing_model }}</div>
                <div class="info-item">🏢 委托人: {{ client if client else '未设置' }}</div>
                <div class="info-item">📝 检测性质: {{ test_nature if test_nature else '未设置' }}</div>
                <div class="info-item" id="current-time">🕒 加载中...</div>
            </div>

            <!-- 监控控制按钮 -->
            <div class="controls" style="justify-content: center; margin-top: 20px;">
                <button class="btn btn-start" id="btn-start" onclick="startMonitoring()">
                    ▶️ 开始监控
                </button>
                <button class="btn btn-stop" id="btn-stop" onclick="stopMonitoring()" disabled>
                    ⏸️ 结束监控
                </button>
                <button class="btn btn-report" id="btn-report" onclick="generateReport()" disabled>
                    📄 生成报告
                </button>
            </div>
            <div id="monitoring-status" style="text-align: center; margin-top: 10px; color: white; font-weight: bold;">
                ⏸️ 监控未启动
            </div>

            <!-- 系统检测结果 -->
            <div class="startup-tests" id="startup-tests-container">
                <h3>🔍 系统模块检测结果</h3>
                <div id="startup-tests-summary" class="test-item test-status-not_tested">
                    <span class="test-icon">⏳</span>
                    <span>正在进行系统检测...</span>
                </div>
            </div>
        </div>
        
        <div class="dashboard">
            <!-- 模块测试详情 -->
            <div class="card module-tests-card">
                <h3>📋 模块检测详情</h3>
                <div id="module-test-details" class="module-test-grid">
                    <div class="loading">
                        <div class="spinner"></div>
                        <div>正在检测系统模块...</div>
                    </div>
                </div>
            </div>

            <!-- 实时状态面板 -->
            <div class="card">
                <h3>📊 实时状态</h3>
                <div class="status-grid">
                    <div class="status-item">
                        <div class="status-label">温度 (°C)</div>
                        <div class="status-value" id="current-temp">--</div>
                    </div>
                    <div class="status-item">
                        <div class="status-label">振动 (g)</div>
                        <div class="status-value" id="current-vibration">--</div>
                    </div>
                    <div class="status-item">
                        <div class="status-label">声音异常分数</div>
                        <div class="status-value" id="current-audio">--</div>
                    </div>
                    <div class="status-item">
                        <div class="status-label">异常事件</div>
                        <div class="status-value" id="anomaly-count">0</div>
                    </div>
                </div>
            </div>
            
            <!-- 温度图表 -->
            <div class="card">
                <h3>🌡️ 温度监控</h3>
                <div class="chart-container">
                    <canvas id="tempChart"></canvas>
                </div>
            </div>
            
            <!-- 振动图表 -->
            <div class="card">
                <h3>📈 振动监控</h3>
                <div class="chart-container">
                    <canvas id="vibrationChart"></canvas>
                </div>
            </div>

            <!-- 声音图表 -->
            <div class="card">
                <h3>🔊 声音监控 <span id="audio-data-source" style="font-size: 0.7em; color: #666;"></span></h3>
                <div class="chart-container">
                    <canvas id="audioChart"></canvas>
                </div>
            </div>

            <!-- 声音波形图 -->
            <div class="card" style="grid-column: 1 / -1;">
                <h3>🎵 声音实时波形</h3>
                <div class="chart-container" style="height: 350px;">
                    <canvas id="audioWaveformChart"></canvas>
                </div>
            </div>
            
            <!-- 拍照控制 -->
            <div class="card">
                <h3>📸 拍照控制</h3>
                <div class="controls">
                    <button class="btn" onclick="takePhoto()">📷 立即拍照</button>
                    <button class="btn" onclick="refreshPhotos()">🔄 刷新照片</button>
                </div>
                <div id="photos-container" class="loading">
                    <div class="spinner"></div>
                    <div>加载照片中...</div>
                </div>
            </div>
            
            <!-- 异常记录 -->
            <div class="card">
                <h3>⚠️ 异常记录</h3>
                <div id="anomaly-list" class="anomaly-list">
                    <div class="loading">
                        <div class="spinner"></div>
                        <div>加载异常记录中...</div>
                    </div>
                </div>
            </div>
        </div>
    </div>

    <!-- 会话列表模态框 -->
    <div id="sessionsModal" class="modal">
        <div class="modal-content" style="max-width: 900px;">
            <div class="modal-header">
                <h2>📂 历史监控会话</h2>
                <button class="modal-close" onclick="closeSessionsModal()">&times;</button>
            </div>
            <div id="sessions-list-container" style="max-height: 500px; overflow-y: auto;">
                <div class="loading">
                    <div class="spinner"></div>
                    <div>加载会话列表中...</div>
                </div>
            </div>
        </div>
    </div>

    <script>
        // 全局变量
        let socket;
        let charts = {};
        let isConnected = false;
        let monitoringStarted = false;  // 监控是否已启动
        let systemCheckCompleted = false;  // 系统检测是否完成
        let startupTestResults = null;  // 启动测试结果

        // 数据存储 - 使用线性坐标轴
        const dataBuffer = {
            temperature: [],
            vibration: [],
            audio: [],
            audio_waveform: [],  // 音频波形数据 - 滚动缓冲区
            maxLength: 100,
            waveformMaxLength: 1000  // 波形缓冲区最大长度
        };

        let dataIndex = 0; // 线性数据索引
        let waveformIndex = 0; // 波形数据索引（用于x坐标）
        let isRealAudioData = false;  // 是否为真实音频数据
        
        // 初始化
        document.addEventListener('DOMContentLoaded', function() {
            initializeSocket();
            initializeCharts();
            updateTime();
            setInterval(updateTime, 1000);
            loadInitialData();
        });
        
        // 初始化Socket连接
        function initializeSocket() {
            socket = io();
            
            socket.on('connect', function() {
                isConnected = true;
                updateConnectionStatus(true);
                showAlert('WebSocket连接成功', 'success');
            });
            
            socket.on('disconnect', function() {
                isConnected = false;
                updateConnectionStatus(false);
                showAlert('WebSocket连接断开', 'error');
            });
            
            socket.on('startup_tests', function(data) {
                updateStartupTestResults(data);
            });
            
            socket.on('temperature_data', function(data) {
                updateTemperatureData(data);
            });
            
            socket.on('vibration_data', function(data) {
                updateVibrationData(data);
            });
            
            socket.on('audio_data', function(data) {
                updateAudioData(data);
            });
            
            socket.on('anomaly_alert', function(data) {
                addAnomalyAlert(data);
                showAlert(`检测到异常: ${data.description}`, 'warning');
            });
            
            socket.on('new_photo', function(data) {
                showAlert('新照片已拍摄', 'success');
                refreshPhotos();
            });

            socket.on('monitoring_status', function(data) {
                updateMonitoringStatus(data.started);
                if (data.message) {
                    showAlert(data.message, data.started ? 'success' : 'warning');
                }
            });

            socket.on('system_check_completed', function(data) {
                systemCheckCompleted = true;
                updateStartupTestResults(data);
                updateStartButton();
                showAlert('系统模块检测完成!', 'success');
            });
        }

        // 开始监控
        function startMonitoring() {
            // 检查系统检测是否完成
            if (!systemCheckCompleted) {
                showAlert('系统模块检测未完成，请等待检测完成后再启动监控', 'warning');
                return;
            }

            if (monitoringStarted) {
                showAlert('监控已经在运行中', 'warning');
                return;
            }

            fetch('/api/start_monitoring', {
                method: 'POST',
                headers: {
                    'Content-Type': 'application/json',
                },
            })
            .then(response => response.json())
            .then(data => {
                if (data.success) {
                    showAlert(data.message, 'success');
                    updateMonitoringStatus(true);
                } else {
                    showAlert(data.message, 'error');
                }
            })
            .catch(error => {
                showAlert('启动监控失败', 'error');
                console.error('启动监控错误:', error);
            });
        }

        // 更新开始按钮状态
        function updateStartButton() {
            const btnStart = document.getElementById('btn-start');
            if (systemCheckCompleted && !monitoringStarted) {
                btnStart.disabled = false;
            } else {
                btnStart.disabled = true;
            }
        }

        // 停止监控
        function stopMonitoring() {
            if (!monitoringStarted) {
                showAlert('监控未在运行', 'warning');
                return;
            }

            if (!confirm('确定要停止监控吗?')) {
                return;
            }

            fetch('/api/stop_monitoring', {
                method: 'POST',
                headers: {
                    'Content-Type': 'application/json',
                },
            })
            .then(response => response.json())
            .then(data => {
                if (data.success) {
                    showAlert(data.message, 'success');
                    updateMonitoringStatus(false);
                } else {
                    showAlert(data.message, 'error');
                }
            })
            .catch(error => {
                showAlert('停止监控失败', 'error');
                console.error('停止监控错误:', error);
            });
        }

        // 生成报告
        function generateReport() {
            if (monitoringStarted) {
                if (!confirm('监控正在运行中，建议先停止监控再生成报告。是否继续生成?')) {
                    return;
                }
            }

            // 显示加载状态
            const btnReport = document.getElementById('btn-report');
            const originalText = btnReport.textContent;
            btnReport.disabled = true;
            btnReport.textContent = '📄 生成中...';

            fetch('/api/generate_report', {
                method: 'POST',
                headers: {
                    'Content-Type': 'application/json',
                },
            })
            .then(response => response.json())
            .then(data => {
                btnReport.disabled = false;
                btnReport.textContent = originalText;

                if (data.success) {
                    showAlert('报告生成成功!', 'success');

                    // 提示用户下载
                    if (confirm('报告生成成功! 是否立即下载?')) {
                        window.open(data.download_url, '_blank');
                    }
                } else {
                    showAlert(data.message, 'error');
                }
            })
            .catch(error => {
                btnReport.disabled = false;
                btnReport.textContent = originalText;
                showAlert('生成报告失败', 'error');
                console.error('生成报告错误:', error);
            });
        }

        // 更新监控状态UI
        function updateMonitoringStatus(started) {
            monitoringStarted = started;
            const statusEl = document.getElementById('monitoring-status');
            const btnStart = document.getElementById('btn-start');
            const btnStop = document.getElementById('btn-stop');
            const btnReport = document.getElementById('btn-report');

            if (started) {
                statusEl.textContent = '▶️ 监控运行中...';
                statusEl.style.color = '#51cf66';
                btnStart.disabled = true;
                btnStop.disabled = false;
                // 监控运行时也可以生成报告
                btnReport.disabled = false;
            } else {
                statusEl.textContent = '⏸️ 监控未启动';
                statusEl.style.color = 'white';
                btnStop.disabled = true;
                btnReport.disabled = false;
                updateStartButton();  // 根据系统检测状态决定开始按钮是否可用
            }
        }
        
        // 更新启动测试结果
        function updateStartupTestResults(testResults) {
            startupTestResults = testResults;
            
            // 更新摘要
            const summaryEl = document.getElementById('startup-tests-summary');
            const statusIcons = {
                'all_passed': '✅',
                'partial_passed': '⚠️',
                'all_failed': '❌',
                'not_tested': '⏳'
            };
            
            summaryEl.className = `test-item test-status-${testResults.status}`;
            summaryEl.innerHTML = `
                <span class="test-icon">${statusIcons[testResults.status]}</span>
                <span>${testResults.message}</span>
            `;
            
            // 更新详细信息
            const detailsEl = document.getElementById('module-test-details');
            if (testResults.details) {
                detailsEl.innerHTML = '';
                
                const moduleInfo = {
                    'temperature': { name: '温度传感器', icon: '🌡️' },
                    'vibration': { name: '振动传感器', icon: '📈' },
                    'audio': { name: '声音录制', icon: '🔊' },
                    'camera': { name: '拍照模块', icon: '📸' }
                };
                
                Object.entries(testResults.details).forEach(([moduleName, moduleResult]) => {
                    const info = moduleInfo[moduleName] || { name: moduleName, icon: '🔧' };
                    
                    const moduleEl = document.createElement('div');
                    moduleEl.className = `module-test-item ${moduleResult.status}`;
                    
                    moduleEl.innerHTML = `
                        <div class="module-test-header">
                            <span class="module-test-icon">${info.icon}</span>
                            <span class="module-test-name">${info.name}</span>
                            <span class="module-test-status status-${moduleResult.status}">
                                ${moduleResult.status.toUpperCase()}
                            </span>
                        </div>
                        <div class="module-test-message">${moduleResult.message}</div>
                        <div class="module-test-duration">测试耗时: ${moduleResult.duration.toFixed(2)}秒</div>
                    `;
                    
                    detailsEl.appendChild(moduleEl);
                });
            }
        }
        
        // 初始化图表 - 使用线性坐标轴
        function initializeCharts() {
            const chartConfig = {
                type: 'line',
                options: {
                    responsive: true,
                    maintainAspectRatio: false,
                    animation: {
                        duration: 0 // 禁用动画以提高性能
                    },
                    scales: {
                        x: {
                            type: 'linear',
                            title: {
                                display: true,
                                text: '时间点'
                            }
                        },
                        y: {
                            beginAtZero: true,
                            title: {
                                display: true
                            }
                        }
                    },
                    plugins: {
                        legend: {
                            display: false
                        }
                    }
                }
            };
            
            // 温度图表
            const tempConfig = JSON.parse(JSON.stringify(chartConfig));
            tempConfig.data = {
                datasets: [{
                    label: '温度',
                    data: [],
                    borderColor: 'rgb(255, 99, 132)',
                    backgroundColor: 'rgba(255, 99, 132, 0.1)',
                    tension: 0.4,
                    pointRadius: 1
                }]
            };
            tempConfig.options.scales.y.title.text = '温度 (°C)';
            charts.temperature = new Chart(document.getElementById('tempChart'), tempConfig);
            
            // 振动图表
            const vibrationConfig = JSON.parse(JSON.stringify(chartConfig));
            vibrationConfig.data = {
                datasets: [{
                    label: '振动',
                    data: [],
                    borderColor: 'rgb(54, 162, 235)',
                    backgroundColor: 'rgba(54, 162, 235, 0.1)',
                    tension: 0.4,
                    pointRadius: 1
                }]
            };
            vibrationConfig.options.scales.y.title.text = '振动 (g)';
            charts.vibration = new Chart(document.getElementById('vibrationChart'), vibrationConfig);

            // 声音图表
            const audioConfig = JSON.parse(JSON.stringify(chartConfig));
            audioConfig.data = {
                datasets: [{
                    label: '声音异常分数',
                    data: [],
                    borderColor: 'rgb(75, 192, 192)',
                    backgroundColor: 'rgba(75, 192, 192, 0.1)',
                    tension: 0.4,
                    pointRadius: 1
                }]
            };
            audioConfig.options.scales.y.title.text = '异常分数';
            audioConfig.options.scales.y.max = 1.0;
            charts.audio = new Chart(document.getElementById('audioChart'), audioConfig);

            // 音频波形图
            const waveformConfig = JSON.parse(JSON.stringify(chartConfig));
            waveformConfig.data = {
                datasets: [{
                    label: '声音波形',
                    data: [],
                    borderColor: 'rgb(153, 102, 255)',
                    backgroundColor: 'rgba(153, 102, 255, 0.1)',
                    tension: 0.4,
                    pointRadius: 0,
                    borderWidth: 2,
                    fill: true
                }]
            };
            waveformConfig.options.scales.y.title.text = '振幅';
            waveformConfig.options.scales.y.min = -1.0;
            waveformConfig.options.scales.y.max = 1.0;
            waveformConfig.options.plugins.legend.display = false;
            charts.audioWaveform = new Chart(document.getElementById('audioWaveformChart'), waveformConfig);
        }
        
        // 更新连接状态
        function updateConnectionStatus(connected) {
            const statusEl = document.getElementById('connection-status');
            if (connected) {
                statusEl.textContent = '🟢 已连接';
                statusEl.className = 'connection-status connected';
            } else {
                statusEl.textContent = '🔴 已断开';
                statusEl.className = 'connection-status disconnected';
            }
        }
        
        // 更新时间
        function updateTime() {
            const now = new Date();
            document.getElementById('current-time').textContent = 
                `🕒 ${now.toLocaleString('zh-CN')}`;
        }
        
        // 更新温度数据
        function updateTemperatureData(data) {
            // 更新实时显示
            document.getElementById('current-temp').textContent = data.temperature.toFixed(1);
            
            // 添加到数据缓冲区
            dataBuffer.temperature.push({
                x: dataIndex,
                y: data.temperature
            });
            
            // 保持数据长度
            if (dataBuffer.temperature.length > dataBuffer.maxLength) {
                dataBuffer.temperature.shift();
                // 重新调整所有数据的x坐标
                dataBuffer.temperature.forEach((point, index) => {
                    point.x = index;
                });
            }
            
            // 更新图表
            charts.temperature.data.datasets[0].data = dataBuffer.temperature;
            charts.temperature.update('none');
            
            dataIndex++;
        }
        
        // 更新振动数据
        function updateVibrationData(data) {
            // 更新实时显示
            document.getElementById('current-vibration').textContent = data.magnitude.toFixed(3);

            // 添加到数据缓冲区
            dataBuffer.vibration.push({
                x: dataIndex,
                y: data.magnitude
            });

            // 保持数据长度
            if (dataBuffer.vibration.length > dataBuffer.maxLength) {
                dataBuffer.vibration.shift();
                // 重新调整所有数据的x坐标
                dataBuffer.vibration.forEach((point, index) => {
                    point.x = index;
                });
            }

            // 更新图表
            charts.vibration.data.datasets[0].data = dataBuffer.vibration;
            charts.vibration.update('none');
        }
        
        // 更新声音数据
        function updateAudioData(data) {
            // 更新实时显示
            document.getElementById('current-audio').textContent = data.score.toFixed(3);

            // 更新数据源指示器
            isRealAudioData = data.is_real || false;
            const sourceEl = document.getElementById('audio-data-source');
            if (isRealAudioData) {
                sourceEl.textContent = '(真实录音数据)';
                sourceEl.style.color = '#51cf66';
            } else {
                sourceEl.textContent = '(模拟数据)';
                sourceEl.style.color = '#ff922b';
            }

            // 添加到数据缓冲区 - 异常分数
            dataBuffer.audio.push({
                x: dataIndex,
                y: data.score
            });

            // 保持数据长度
            if (dataBuffer.audio.length > dataBuffer.maxLength) {
                dataBuffer.audio.shift();
                // 重新调整所有数据的x坐标
                dataBuffer.audio.forEach((point, index) => {
                    point.x = index;
                });
            }

            // 更新异常分数图表
            charts.audio.data.datasets[0].data = dataBuffer.audio;
            charts.audio.update('none');

            // 更新波形图 - 滚动追加方式（每个点逐个添加）
            if (data.waveform && data.waveform.length > 0) {
                // 将每个新的波形点追加到缓冲区
                data.waveform.forEach(amplitude => {
                    dataBuffer.audio_waveform.push({
                        x: waveformIndex,
                        y: amplitude
                    });
                    waveformIndex++;
                });

                // 保持波形缓冲区长度（超出时删除最旧的点）
                while (dataBuffer.audio_waveform.length > dataBuffer.waveformMaxLength) {
                    dataBuffer.audio_waveform.shift();
                }

                // 重新调整x坐标，使其连续（从0开始）
                const startX = waveformIndex - dataBuffer.audio_waveform.length;
                dataBuffer.audio_waveform.forEach((point, index) => {
                    point.x = startX + index;
                });

                // 更新波形图表
                charts.audioWaveform.data.datasets[0].data = dataBuffer.audio_waveform;
                charts.audioWaveform.update('none');
            }
        }
        
        // 拍照功能
        function takePhoto() {
            fetch('/api/take_photo', {
                method: 'POST',
                headers: {
                    'Content-Type': 'application/json',
                },
            })
            .then(response => response.json())
            .then(data => {
                if (data.success) {
                    showAlert('拍照成功!', 'success');
                    setTimeout(refreshPhotos, 1000);
                } else {
                    showAlert('拍照失败: ' + data.message, 'error');
                }
            })
            .catch(error => {
                showAlert('拍照请求失败', 'error');
                console.error('拍照错误:', error);
            });
        }
        
        // 刷新照片
        function refreshPhotos() {
            const container = document.getElementById('photos-container');
            container.innerHTML = '<div class="loading"><div class="spinner"></div><div>加载照片中...</div></div>';
            
            fetch('/api/photos')
            .then(response => response.json())
            .then(photos => {
                if (photos.length === 0) {
                    container.innerHTML = '<div style="text-align: center; color: #666; padding: 20px;">暂无照片</div>';
                    return;
                }
                
                const photosGrid = document.createElement('div');
                photosGrid.className = 'photos-grid';
                
                photos.forEach(photo => {
                    const photoItem = document.createElement('div');
                    photoItem.className = 'photo-item';
                    
                    photoItem.innerHTML = `
                        <img src="${photo.path}" alt="照片" onclick="showPhotoModal('${photo.path}')">
                        <div class="photo-timestamp">${photo.created}</div>
                    `;
                    
                    photosGrid.appendChild(photoItem);
                });
                
                container.innerHTML = '';
                container.appendChild(photosGrid);
            })
            .catch(error => {
                container.innerHTML = '<div style="text-align: center; color: #ff6b6b; padding: 20px;">照片加载失败</div>';
                console.error('照片加载错误:', error);
            });
        }
        
        // 加载初始数据
        function loadInitialData() {
            // 加载系统状态
            fetch('/api/status')
            .then(response => response.json())
            .then(status => {
                document.getElementById('anomaly-count').textContent = status.anomaly_count;

                // 更新系统检测状态
                if (status.system_check_completed !== undefined) {
                    systemCheckCompleted = status.system_check_completed;
                    updateStartButton();
                }

                // 更新监控状态
                if (status.monitoring_started !== undefined) {
                    updateMonitoringStatus(status.monitoring_started);
                }

                // 加载启动测试结果(如果有)
                if (status.startup_tests) {
                    updateStartupTestResults(status.startup_tests);
                }
            });

            // 加载启动测试结果
            fetch('/api/test_results')
            .then(response => response.json())
            .then(results => {
                updateStartupTestResults(results);
            });

            // 加载异常记录
            loadAnomalies();

            // 加载照片
            refreshPhotos();
        }
        
        // 加载异常记录
        function loadAnomalies() {
            const container = document.getElementById('anomaly-list');
            container.innerHTML = '<div class="loading"><div class="spinner"></div><div>加载异常记录中...</div></div>';
            
            fetch('/api/anomalies')
            .then(response => response.json())
            .then(anomalies => {
                if (anomalies.length === 0) {
                    container.innerHTML = '<div style="text-align: center; color: #51cf66; padding: 20px;">✅ 暂无异常记录</div>';
                    return;
                }
                
                container.innerHTML = '';
                anomalies.forEach(anomaly => {
                    addAnomalyToList(anomaly);
                });
            })
            .catch(error => {
                container.innerHTML = '<div style="text-align: center; color: #ff6b6b; padding: 20px;">异常记录加载失败</div>';
                console.error('异常记录加载错误:', error);
            });
        }
        
        // 添加异常到列表
        function addAnomalyToList(anomaly) {
            const container = document.getElementById('anomaly-list');
            const anomalyItem = document.createElement('div');
            anomalyItem.className = `anomaly-item ${anomaly.severity}`;
            
            anomalyItem.innerHTML = `
                <div style="display: flex; justify-content: space-between; align-items: center;">
                    <div>
                        <strong>${anomaly.type.toUpperCase()}</strong>
                        <div style="margin: 5px 0; color: #666;">${anomaly.description}</div>
                        <small>${anomaly.timestamp}</small>
                    </div>
                    <div style="text-align: right; font-size: 0.9em;">
                        ${anomaly.temperature > 0 ? `温度: ${anomaly.temperature.toFixed(1)}°C<br>` : ''}
                        ${anomaly.vibration > 0 ? `振动: ${anomaly.vibration.toFixed(3)}g<br>` : ''}
                        ${anomaly.audio_score > 0 ? `声音: ${anomaly.audio_score.toFixed(3)}` : ''}
                    </div>
                </div>
            `;
            
            container.insertBefore(anomalyItem, container.firstChild);
            
            // 限制显示数量
            while (container.children.length > 20) {
                container.removeChild(container.lastChild);
            }
        }
        
        // 添加异常警报
        function addAnomalyAlert(anomaly) {
            addAnomalyToList(anomaly);
            
            // 更新异常计数
            const currentCount = parseInt(document.getElementById('anomaly-count').textContent);
            document.getElementById('anomaly-count').textContent = currentCount + 1;
        }
        
        // 显示提示信息
        function showAlert(message, type) {
            const alertContainer = document.getElementById('alert-container');
            const alert = document.createElement('div');
            alert.className = `alert alert-${type}`;
            alert.textContent = message;
            
            alertContainer.appendChild(alert);
            
            // 显示动画
            setTimeout(() => {
                alert.classList.add('show');
            }, 100);
            
            // 自动隐藏
            setTimeout(() => {
                alert.classList.remove('show');
                setTimeout(() => {
                    if (alert.parentNode) {
                        alert.parentNode.removeChild(alert);
                    }
                }, 300);
            }, 3000);
        }
        
        // 显示照片模态框
        function showPhotoModal(photoPath) {
            const modal = document.createElement('div');
            modal.style.cssText = `
                position: fixed;
                top: 0;
                left: 0;
                width: 100%;
                height: 100%;
                background: rgba(0,0,0,0.8);
                display: flex;
                justify-content: center;
                align-items: center;
                z-index: 2000;
                cursor: pointer;
            `;

            const img = document.createElement('img');
            img.src = photoPath;
            img.style.cssText = `
                max-width: 90%;
                max-height: 90%;
                border-radius: 10px;
                box-shadow: 0 10px 30px rgba(0,0,0,0.5);
            `;

            modal.appendChild(img);
            document.body.appendChild(modal);

            modal.addEventListener('click', () => {
                document.body.removeChild(modal);
            });
        }

        // ========== 配置相关函数 ==========

        // 打开配置模态框
        function openConfigModal() {
            // 加载当前配置
            fetch('/api/config')
            .then(response => response.json())
            .then(config => {
                // 填充表单
                document.getElementById('device_type').value = config.device_type || '轴承';
                document.getElementById('test_name').value = config.test_name || '';
                document.getElementById('operator').value = config.operator || '';
                document.getElementById('bearing_model').value = config.bearing_model || '';
                document.getElementById('client').value = config.client || '';
                document.getElementById('test_nature').value = config.test_nature || '';

                // 显示模态框
                document.getElementById('configModal').classList.add('show');
            })
            .catch(error => {
                console.error('加载配置失败:', error);
                showAlert('加载配置失败', 'error');
            });
        }

        // 关闭配置模态框
        function closeConfigModal() {
            document.getElementById('configModal').classList.remove('show');
        }

        // 保存配置
        document.getElementById('configForm').addEventListener('submit', function(e) {
            e.preventDefault();

            // 收集表单数据
            const formData = {
                device_type: document.getElementById('device_type').value,
                test_name: document.getElementById('test_name').value,
                operator: document.getElementById('operator').value,
                bearing_model: document.getElementById('bearing_model').value,
                client: document.getElementById('client').value,
                test_nature: document.getElementById('test_nature').value
            };

            // 发送到服务器
            fetch('/api/config', {
                method: 'POST',
                headers: {
                    'Content-Type': 'application/json',
                },
                body: JSON.stringify(formData)
            })
            .then(response => response.json())
            .then(data => {
                if (data.success) {
                    showAlert('配置更新成功！', 'success');
                    closeConfigModal();

                    // 更新页面显示的配置信息
                    updateDisplayedConfig(data.config);
                } else {
                    showAlert(data.message, 'error');
                }
            })
            .catch(error => {
                console.error('保存配置错误:', error);
                showAlert('保存配置失败', 'error');
            });
        });

        // 更新页面显示的配置信息
        function updateDisplayedConfig(config) {
            // 更新头部显示的信息
            const infoItems = document.querySelector('.header .info');
            if (infoItems) {
                infoItems.querySelector('.info-item:nth-child(1)').textContent = `📋 测试: ${config.test_name}`;
                infoItems.querySelector('.info-item:nth-child(2)').textContent = `👤 操作员: ${config.operator}`;
                infoItems.querySelector('.info-item:nth-child(3)').textContent = `⚙️ 设备型号: ${config.bearing_model}`;
                infoItems.querySelector('.info-item:nth-child(4)').textContent = `🏢 委托人: ${config.client || '未设置'}`;
                infoItems.querySelector('.info-item:nth-child(5)').textContent = `📝 检测性质: ${config.test_nature || '未设置'}`;
            }

            // 更新页面标题
            const headerTitle = document.querySelector('.header h1');
            if (headerTitle && config.device_type) {
                headerTitle.textContent = `🔧 Web版${config.device_type}监控系统`;
            }
        }

        // 点击模态框外部关闭
        document.getElementById('configModal').addEventListener('click', function(e) {
            if (e.target === this) {
                closeConfigModal();
            }
        });

        // ========== 会话下载相关函数 ==========

        // 下载最新会话数据包
        function downloadLatestSession() {
            showAlert('正在准备下载最新会话数据...', 'success');
            window.location.href = '/api/download/latest_session';
        }

        // 显示会话列表模态框
        function showSessionsModal() {
            document.getElementById('sessionsModal').classList.add('show');
            loadSessionsList();
        }

        // 关闭会话列表模态框
        function closeSessionsModal() {
            document.getElementById('sessionsModal').classList.remove('show');
        }

        // 点击会话模态框外部关闭
        document.getElementById('sessionsModal').addEventListener('click', function(e) {
            if (e.target === this) {
                closeSessionsModal();
            }
        });

        // 加载会话列表
        function loadSessionsList() {
            const container = document.getElementById('sessions-list-container');
            container.innerHTML = '<div class="loading"><div class="spinner"></div><div>加载会话列表中...</div></div>';

            fetch('/api/sessions')
            .then(response => response.json())
            .then(data => {
                if (!data.success || data.sessions.length === 0) {
                    container.innerHTML = '<div style="text-align: center; color: #666; padding: 40px;">暂无历史会话数据</div>';
                    return;
                }

                // 生成会话列表HTML
                let html = '<div style="display: grid; gap: 15px;">';

                data.sessions.forEach((session, index) => {
                    const sessionDate = session.start_time ? session.start_time.split(' ')[0] : '未知日期';
                    const sessionTime = session.start_time ? session.start_time.split(' ')[1] : '';

                    html += `
                        <div style="
                            background: #f8f9ff;
                            border: 1px solid #e0e0e0;
                            border-radius: 10px;
                            padding: 20px;
                            transition: all 0.3s ease;
                            cursor: pointer;
                        " onmouseover="this.style.boxShadow='0 4px 12px rgba(0,0,0,0.15)'"
                           onmouseout="this.style.boxShadow='none'">
                            <div style="display: flex; justify-content: space-between; align-items: flex-start;">
                                <div style="flex: 1;">
                                    <div style="font-size: 1.2em; font-weight: bold; color: #667eea; margin-bottom: 10px;">
                                        ${index === 0 ? '🌟 ' : ''}${session.test_name || session.session_id}
                                    </div>
                                    <div style="color: #666; font-size: 0.9em; margin-bottom: 5px;">
                                        📅 开始时间: ${sessionDate} ${sessionTime}
                                    </div>
                                    <div style="color: #666; font-size: 0.9em; margin-bottom: 5px;">
                                        👤 操作员: ${session.operator || '未设置'}
                                    </div>
                                    <div style="color: #666; font-size: 0.9em; margin-bottom: 5px;">
                                        🏭 设备类型: ${session.device_type || '未设置'}
                                    </div>
                                    <div style="color: #999; font-size: 0.85em; margin-top: 8px;">
                                        会话ID: ${session.session_id}
                                    </div>
                                </div>
                                <div style="margin-left: 20px;">
                                    <button onclick="downloadSession('${session.session_id}')"
                                            class="btn"
                                            style="padding: 10px 20px; white-space: nowrap;">
                                        📥 下载
                                    </button>
                                </div>
                            </div>
                        </div>
                    `;
                });

                html += '</div>';
                container.innerHTML = html;
            })
            .catch(error => {
                console.error('加载会话列表错误:', error);
                container.innerHTML = '<div style="text-align: center; color: #ff6b6b; padding: 40px;">加载会话列表失败</div>';
                showAlert('加载会话列表失败', 'error');
            });
        }

        // 下载指定会话数据包
        function downloadSession(sessionId) {
            showAlert(`正在准备下载会话: ${sessionId}`, 'success');
            window.location.href = `/api/download/session/${sessionId}`;
        }

        // ========== 报告查看相关函数 ==========

        // 显示报告列表模态框
        function showReportsModal() {
            document.getElementById('reportsModal').classList.add('show');
            loadReportsList();
        }

        // 关闭报告列表模态框
        function closeReportsModal() {
            document.getElementById('reportsModal').classList.remove('show');
        }

        // 点击报告模态框外部关闭
        document.getElementById('reportsModal').addEventListener('click', function(e) {
            if (e.target === this) {
                closeReportsModal();
            }
        });

        // 加载报告列表
        function loadReportsList() {
            const container = document.getElementById('reports-list-container');
            container.innerHTML = '<div class="loading"><div class="spinner"></div><div>加载报告列表中...</div></div>';

            fetch('/api/reports')
            .then(response => response.json())
            .then(data => {
                if (!data.success || data.reports.length === 0) {
                    container.innerHTML = '<div style="text-align: center; color: #666; padding: 40px;">暂无生成的报告<br><small style="color: #999; margin-top: 10px; display: block;">请先生成监控报告</small></div>';
                    return;
                }

                // 生成报告列表HTML
                let html = '<div style="display: grid; gap: 15px;">';

                data.reports.forEach((report, index) => {
                    const reportDate = report.created_time ? report.created_time.split(' ')[0] : '未知日期';
                    const reportTime = report.created_time ? report.created_time.split(' ')[1] : '';
                    const fileSize = (report.file_size / 1024).toFixed(1); // KB

                    html += `
                        <div style="
                            background: #f8f9ff;
                            border: 1px solid #e0e0e0;
                            border-radius: 10px;
                            padding: 20px;
                            transition: all 0.3s ease;
                        " onmouseover="this.style.boxShadow='0 4px 12px rgba(0,0,0,0.15)'"
                           onmouseout="this.style.boxShadow='none'">
                            <div style="display: flex; justify-content: space-between; align-items: flex-start;">
                                <div style="flex: 1;">
                                    <div style="font-size: 1.2em; font-weight: bold; color: #667eea; margin-bottom: 10px;">
                                        📕 ${report.test_name}
                                    </div>
                                    <div style="color: #666; font-size: 0.9em; margin-bottom: 5px;">
                                        📅 生成时间: ${reportDate} ${reportTime}
                                    </div>
                                    <div style="color: #666; font-size: 0.9em; margin-bottom: 5px;">
                                        📁 文件名: ${report.filename}
                                    </div>
                                    <div style="color: #666; font-size: 0.9em; margin-bottom: 5px;">
                                        📊 类型: <span style="color: #ff6b6b; font-weight: bold;">PDF</span>
                                    </div>
                                    <div style="color: #666; font-size: 0.9em; margin-bottom: 5px;">
                                        💾 大小: ${fileSize} KB
                                    </div>
                                    <div style="color: #999; font-size: 0.85em; margin-top: 8px;">
                                        会话ID: ${report.session_id}
                                    </div>
                                </div>
                                <div style="margin-left: 20px;">
                                    <button onclick="downloadReport('${report.session_id}', '${report.filename}')"
                                            class="btn"
                                            style="padding: 12px 24px; white-space: nowrap;">
                                        📥 下载PDF
                                    </button>
                                </div>
                            </div>
                        </div>
                    `;
                });

                html += '</div>';
                container.innerHTML = html;
            })
            .catch(error => {
                console.error('加载报告列表错误:', error);
                container.innerHTML = '<div style="text-align: center; color: #ff6b6b; padding: 40px;">加载报告列表失败</div>';
                showAlert('加载报告列表失败', 'error');
            });
        }

        // 下载报告文件
        function downloadReport(sessionId, filename) {
            showAlert(`正在准备下载报告: ${filename}`, 'success');
            window.location.href = `/api/reports/${sessionId}/${filename}`;
        }

        // 页面卸载时清理资源
        window.addEventListener('beforeunload', function() {
            if (socket) {
                socket.disconnect();
            }
        });
    </script>
</body>
</html>